package jalgebrava.group.groups;

import jalgebrava.group.Group;
import jalgebrava.group.Subgroup;
import jalgebrava.group.Subset;
import jalgebrava.group.morphisms.Automorphism;
import jalgebrava.group.morphisms.Homomorphism;
import jalgebrava.group.permutation.Permutation;
import jalgebrava.util.Pair;

/**
 * Basic groups constructions.
 */
public final class Groups {
	@SuppressWarnings("unused") // just there to keep EMMA happy
	private final static Groups instance = new Groups();
	private Groups() {
		// hidden
	}
	
	/**
	 * Integers modulo n
	 * @param n
	 * @return a cyclic group
	 */ 
	public final static Group<Integer> cyclic(int n) {
		return CyclicGroupFactory.mk(n);
	}
	
	public final static <G,H> Group<Pair<G,H>> directProduct(Group<G> g, Group<H> h) {
		return DirectProductGroupFactory.mk(g,h);
	}
	
	public final static Group<Permutation> symmetric(int n) {
		return SymmetricGroupFactory.mk(n);
	}
	public final static Group<Integer> relabel(Group<?> g) {
		return RelabeledGroupFactory.mk(g);
	}
	public final static Group<Integer> blackBox(String desc, final int[][] m) {
		return BlackBoxGroupFactory.mk(desc, m, null);
	}
	
	public final static <G> Group<Subset<G>> quotient(Group<G> g, Subgroup<G> h) {
		return QuotientGroupFactory.mk(g,h);
	}
	
	public final static Group<String> freeStringGroup() {
		return FreeStringGroupFactory.mk();
	}
	
	public final static <G> AccountingGroup<G> accountingGroup(Group<G> g) {
		return new AccountingGroup<G>(g);
	}
	// n is the number of elements! guaranteed to be even
	public final static Group<Pair<Integer, Boolean>> dihedral(int n) {
		return DihedralGroupFactory.mk(n);
	}
	
	public final static Group<Integer> quaternion(int n) {
		return QuaternionGroupFactory.mk(n);
	}
	
	public final static <G,H> Group<Pair<G,H>> semidirectProduct(Group<G> g, Group<H> h, Homomorphism<H, Automorphism<G>> phi) {
		return SemidirectProductFactory.mk(g,h, phi);
	}
}
